package provider_consumer;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

public class Test {

    @org.junit.Test
    public void test1() {
        FoodBox foodBox = new FoodBox();
        for (int i = 0; i < 5; i++) {
            Consumer consumer = new Consumer();
            consumer.setFoodBox(foodBox);
            new Thread(() -> {
                while (true) {
                    consumer.eat();
                }
            }).start();

            Producer producer = new Producer();
            producer.setFoodBox(foodBox);
            new Thread(() -> {
                while (true) {
                    producer.put();
                }
            }).start();

        }

        while (true) {

        }

    }

    class Producer {
        private FoodBox foodBox;

        public FoodBox getFoodBox() {
            return foodBox;
        }

        public void setFoodBox(FoodBox foodBox) {
            this.foodBox = foodBox;
        }

        public void put() {

            this.foodBox.add(new Food(foodBox.foodList.size() + 1));
        }
    }

    class Consumer {
        private FoodBox foodBox;

        public void eat() {
            this.foodBox.remove();

        }

        public FoodBox getFoodBox() {
            return foodBox;
        }

        public void setFoodBox(FoodBox foodBox) {
            this.foodBox = foodBox;
        }
    }

    class Food {
        public int id;

        public Food(int id) {
            this.id = id;
        }
    }

    class FoodBox {
        private List<Food> foodList = new ArrayList<>();
        private int maxSize = 10;


        public synchronized void add(Food food) {
            //为什么要使用while？
            //设想如果多个生产者都陷入了wait，然后通过notifyAll依次苏醒，在直到某一个苏醒时目前的食物容量已经重新又被填满了，因此需要用while确保正确性
            while (foodList.size() == maxSize) {
                try {
                    System.out.println("食物满了，等人吃一点。。");
                    this.wait();
                    System.out.println("又可以造食物了。。");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            foodList.add(food);
            this.notifyAll();
        }

        public synchronized Food remove() {
            while (foodList.isEmpty()) {
                try {
                    System.out.println("食物空了，等人造一点。。");
                    this.wait();
                    System.out.println("食物有了，可以吃了。。");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.notifyAll();
            return foodList.remove(0);
        }
    }


    @org.junit.Test
    public void te() {
        ReentrantLock lock = new ReentrantLock();

        new Thread(() -> {
            lock.lock();
            lock.unlock();
            while (true) ;
        }).start();
        new Thread(() -> {
            lock.lock();

            while (true) ;
        }).start();
        while (true) ;
    }

}
